import { Base } from '../base.js'
import * as THREE from 'three'
import {Fade} from './fade.js'
import { Move } from './move.js'
import { Plan } from './plan.js'
interface Res {
    [key: string]: THREE.Group
}
export type PlayerAnimate = {
    prev: any,
    mixer:THREE.AnimationMixer
    common(name:string):Promise<void>
    player: THREE.Group | THREE.Object3D
    walk():Promise<void>
    die():Promise<void>
    run():Promise<void>
    idle():Promise<void>
    changeRole(name:string):void
    crawling():Promise<void>
    baoqi():Promise<void>
    goTo(name:string | THREE.Vector3):Promise<void>
    positionTo(name:string):void
    moveTo(position:THREE.Vector3, isRun:boolean, isIdle:boolean):Promise<void>
}

let _actionData:Res = {}
export const Utils = {
    _actionData: _actionData,
    async loadRes(base: Base) {
        const data:Res = {
            
        }
        const heros = ['boy', 'girl'] // , 'guai1'
        const actions = ['idle', 'baoqi', 'crawling', 'die', 'run', 'walk']
        actions.push(...new Array(45).fill('').map((v, i) => `dance`+(i+1)))
        for(let i=0;i<heros.length;i++) {
            data[`${heros[i]}`] = await base.createFbx(`hero/${heros[i]}`)
        }
        const loadingEl = document.getElementById('loading')
        if (loadingEl) {
            loadingEl.style.display = 'block'
            for(let i=0;i<actions.length;i++) {
                data[`action/${actions[i]}`] = await base.createFbx(`hero/action/${actions[i]}`)
                this._actionData[`action/${actions[i]}`] = data[`action/${actions[i]}`]
                this._actionData[`action/${actions[i]}`].userData.name = actions[i]
                loadingEl.innerHTML = `资源加载中... ${i + 1}/${actions.length}`
            }
            setTimeout(() => {
                loadingEl.style.display = ''
            }, 500)
        }
        
        return data
    },
    createAnimate(player:THREE.Group | THREE.Object3D, onDie: (player:THREE.Group | THREE.Object3D) => void) {
        const mixer = new THREE.AnimationMixer(player)
        const actions: THREE.AnimationAction[] = []
        const _actions:{
            [key: string]: THREE.AnimationAction
        } = {

        }
        Fade.setMixer(mixer, player.uuid)
        for(const n in this._actionData) {
            actions.push(mixer.clipAction(this._actionData[n].animations[0]))
            _actions[n + '/' + player.uuid] = actions[actions.length - 1]
            
            Fade.activateAction(_actions[n + '/' + player.uuid], actions.length === 1 ? 1 : 0)
            
        }
        const isInitObj:any = {}
        mixer.addEventListener( 'loop',  e => {
            if (e.action === _actions['action/die/' + player.uuid]) {
                if (isInitObj['action/die/' + player.uuid] && e.action.weight > 0) {
                    onDie(player)
                    player.parent?.remove(player)
                } else {
                    isInitObj['action/die/' + player.uuid] = true
                }
                
            }
        });
        // const loopFinished = (e:any) => {
        //     if (e.action === _actions['action/die/' + player.uuid]) {
                
        //         e.action.number = e.action.number || 0
        //         e.action.number++
        //         if (e.action.number >= 2) {
        //             e.action.clampWhenFinished = true
        //             mixer.removeEventListener( 'loop',  loopFinished);
                    
        //         }
        //         e.action.setLoop(THREE.LoopOnce, 1)
        //         console.log(e.action.number)
        //     }
        // }
        // 
        
        
        let prev:any = null
		return {
            prev: prev,
            mixer,
            player,
            async common(name:string) {
                const key = 'action/' + name + '/' + player.uuid
                for(const n in _actions) {
                    _actions[n].weight = 0
                }
                if (this.prev) {
                    _actions[key].weight = 1
                    // await Fade.prepareCrossFade(this.prev, _actions[key], 1, player.uuid)
                    // this.prev = _actions[key]
                } else {
                    // await Fade.prepareCrossFade(_actions['action/idle/' + player.uuid], _actions[key], 1, player.uuid)
                    _actions[key].weight = 1
                    this.prev = _actions[key]
                }
            },
            walk() {
                return this.common('walk')
            },
            die() {
                return this.common('die')
            },
            run() {
                return this.common('run')
            },
            idle() {
                return this.common('idle')
            },
            crawling() {
                return this.common('crawling')
            },
            baoqi() {
                return this.common('baoqi')
            },
            changeRole(name:string) {

            },
            async goTo(name:string | THREE.Vector3) {
                // 获取去房间5的路线规划
                const list =  Plan.toRoom(name, player)
                
                for(let i=0;i<list.length;i++) {
                    await this.moveTo(list[i], i === 0, i === list.length - 1)
                }
            },
            async positionTo(name:string) {
                Plan.to(name, player)
            },
            async moveTo(position:THREE.Vector3, isRun = true, isIdle = true) {
                await Move.to(player, position, async () => {
                    if (isRun) {
                        await this.run()
                    }
                }, async () => {
                    if (isIdle) {
                        await this.idle()
                    }
                })
            }
        }
    },
    async wait(fn:() => void, time = 2000) {
        return new Promise(res => {
            setTimeout(() => {
                res(true)
                fn()
            }, time)
        })
    },
    getFreePoint() {
        // 自由活动的坐标范围
        const freePoints = [
			[12.5, 0, -6],
			[12.5, 0, 6],
			[-23, 0, 6],
			[-23, 0, -6]
		]
        const x = Math.random() * 45.5 - 23
        const z = Math.random() * 12 - 6

        return new THREE.Vector3(x, 0, z)
    }
}